package org.example.skytool.jw;

import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.example.dao.entity.user.UStudent;
import org.example.exception.JwErrorException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.Objects;
import java.util.regex.Pattern;

/**
 * @author 22449
 */
@Component
public class JwUtil {

    @Resource
    private OkHttpClient okHttpClient;

    private static final String XS_MAIN_JSP_URL = "http://xk.csust.edu.cn/jsxsd/framework/xsMain_new.jsp?t1=1";

    //JSESSIONID匹配的正则表达式
    private static final Pattern JW_JSESSIONID_Patten = Pattern.compile("^JSESSIONID=.*");


    public String getLoginCookie(String stuNum, String password) {
        String loginUrl = "http://xk.csust.edu.cn/Logon.do?method=logon";
        Response response, updateCookieResponse;
        //[0]:cookie [1]:用于密码处理
        String[] jwCode = getJwCode();
        //对密码进行处理，可能是Base64处理
        String encoded = encodePsd(stuNum, password, jwCode[1]);
        OkHttpClient okHttpClient = new OkHttpClient.Builder().followRedirects(false).build();
        FormBody formBody = new FormBody.Builder()
                .add("userAccount", stuNum)
                .add("userPassword", password)
                .add("encoded", encoded).build();
        Request jwLoginRequest = new Request.Builder()
                .header("Cookie", "JSESSIONID=" + jwCode[0])
                .header("Host", "xk.csust.edu.cn")
                .header("Origin", "http://xk.csust.edu.cn")
                .header("Referer", "http://xk.csust.edu.cn/")
                .url(loginUrl)
                .post(formBody)
                .build();
        try {
            response = okHttpClient.newCall(jwLoginRequest).execute();
        } catch (Exception e) {
            throw new JwErrorException("获取登录cookie失败");
        }
        String updateCookieUrl = response.header("Location");
        if (updateCookieUrl == null) {
            throw new JwErrorException("获取登录cookie失败");
        }
        OkHttpClient updateCookieClient = new OkHttpClient.Builder().followRedirects(false).build();
        Request updateCookieRequest = new Request.Builder()
                .header("Cookie", jwCode[0])
                .header("Referer", "http://xk.csust.edu.cn/")
                .url(updateCookieUrl)
                .build();
        try {
            updateCookieResponse = updateCookieClient.newCall(updateCookieRequest).execute();
        } catch (Exception e) {
            throw new JwErrorException("获取登录cookie失败");
        }
        String header = updateCookieResponse.header("Set-Cookie");
        if (header == null) {
            throw new JwErrorException("获取登录cookie失败");
        }
        String[] split = header.split(";");
        for (String s : split) {
            if (JW_JSESSIONID_Patten.matcher(s).matches()) {
                return s;
            }
        }
        throw new JwErrorException("获取登录cookie失败");
    }

    public UStudent getStuInfo(String cookie) {
        //学生主页面
        String url = "http://xk.csust.edu.cn/jsxsd/framework/xsMain_new.jsp?t1=1";
        Request request = new Request.Builder()
                .header("Cookie", cookie)
                .header("Host", "xk.csust.edu.cn")
                .header("Referer", "http://xk.csust.edu.cn/jsxsd/framework/xsMain.jsp")
                .url(url)
                .build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            String htmlText = Objects.requireNonNull(response.body()).string();
            response.close();
            Document doc = Jsoup.parse(htmlText);
            Element body = doc.body();
            Elements stuInfoDivs = body.getElementsByClass("middletopdwxxcont");
            int index = 0;
            UStudent jwStuInfo = new UStudent();
            for (Element infoDiv : stuInfoDivs) {
                switch (index) {
                    case 1:
                        jwStuInfo.setName(infoDiv.text());
                        break;
                    case 2:
                        jwStuInfo.setStuNum(infoDiv.text());
                        break;
                    case 3:
                        jwStuInfo.setCollege(infoDiv.text());
                        break;
                    case 4:
                        jwStuInfo.setMajor(infoDiv.text());
                        break;
                    case 5:
                        jwStuInfo.setClassName(infoDiv.text());
                        break;
                }
                index++;
            }
            return jwStuInfo;
        } catch (Exception e) {
            throw new JwErrorException("获取学生基本信息失败，错误原因：" + e.getMessage());
        }

    }

    private String[] getJwCode() {
        String url = "http://xk.csust.edu.cn/Logon.do?method=logon&flag=sess";
        Request jwCodeRequest = new Request.Builder().url(url).build();
        try {
            Response response = okHttpClient.newCall(jwCodeRequest).execute();
            String header = response.header("Set-Cookie");
            String[] split = header.split(";");
            String[] result = new String[2];
            for (String s : split) {
                if (JW_JSESSIONID_Patten.matcher(s).matches()) {
                    result[0] = s.split("=")[1];
                }
            }
            result[1] = response.body().string();
            response.close();
            return result;
        } catch (Exception e) {
            throw new JwErrorException("教务系统获取加密字符串失败，错误原因：" + e.getMessage());
        }

    }


    private static String encodePsd(String username, String password, String dataStr) {
        String[] splitCode = dataStr.split("#");
        String scode = splitCode[0];
        String sxh = splitCode[1];
        String code = username + "%%%" + password;
        StringBuilder encode = new StringBuilder();
        for (int i = 0; i < code.length(); i++) {
            if (i < 20) {
                int theIndex = Integer.parseInt(sxh.substring(i, i + 1));
                encode.append(code.charAt(i)).append(scode, 0, theIndex);
                scode = scode.substring(theIndex);
            } else {
                encode.append(code.substring(i));
                i = code.length();
            }
        }
        return encode.toString();
    }

}
